Vue项目实战(PC端)

相关资料

  1. 饿了么UI库: https://element.eleme.cn/#/zh-CN/component/table

(一) 下载和运行项目

  1. 线上地址: http://nongye.huruqing.cn
  2. pc端: git@gitee.com:huruqing/nongye-admin-template.git
    1. npm i 安装依赖
    2. npm run serve 运行项目
  3. 服务器端: git@gitee.com:huruqing/nongye-server-template.git
    1. 进入项目
    2. npm i 安装依赖
    3. npm run dev 运行项目
  4. 数据库
    1. 全局安装 json-server npm i json-server@0.8 -g
    2. 进入/nongye-server-template/db, 执行 npm i
    3. 启动数据库 进入/nongye-server-template, 执行 npm run json

(二) 路由守卫

vue-router的路由守卫和axios拦截器有着类似的作用

  1. from 当前路由
  2. to 要前往的目标路由
  3. next 执行下一步操作
  • next() 进入到目标路由(相当于放行)
  • next({ path: '/xxx' }) 跳转到/xxx 路由
// 最初的路由
const router = new Router({
  mode: "history",
  routes: initRoutes,
});

// 路由白名单
const whiteList = ["/login"];
// 路由守卫
router.beforeEach((to, from, next) => {
  if (store.state.token) {
    //已经登录: 如果路由是登录页,默认跳转到首页
    if (to.path == "/login") {
      next({
        path: "/home/dashboard",
      });
    } else {
      next();
    }
  } else {
    	next("/login");
    //没有登录,路由是否在白名单中
    if (whiteList.includes(to.path)) {
      //放行
      next();
    } else {
      //没在白名单,跳到登录页面
      next("/login");
    }
  }
});

(三) 用户权限控制

用户权限控制的思路是:

  1. 前端一开始的路由只配置了一些基本的路由
  2. 用户登录之后, 后台会给前端返回一个角色字段(比如type), 表明用户的身份
  3. 前端就根据用户的身份(角色字段)配置不同的路由(有的公司由后台返回)
  4. 前端使用router.addRoutes方法动态添加权限路由。
  5. 在后台管理系统的侧边栏一般根据路由数组动态渲染,这样不同角色能看到的列表就不一样。

实践: 在各个代码的关键节点打上断点, 查看整个流程 ​

(四) 动态渲染侧边栏

  1. 让侧边栏组件(layout)作为所有需要侧边栏的父路由组件(父路由有什么内容, 子路由就有什么内容)
  2. 刚开始创建路由的时候, 只创建无需登录就能访问的路由
  3. 根据设置权限设置多个路由数组(routes)
  4. 登录成功的时候添加加权限动态添加相应的路由数组, 并把路由数组存入vuex的store(仓库)
  5. 渲染侧边栏的时候, 把路由数组(routes)从store取出, 使用v-for进行动态渲染

(五) 深拷贝和浅拷贝

  1. 基本数据类型, 拷贝与被拷贝的变量之间, 任何一方修改了都不会影响另一方
  2. 引用数据类型的拷贝就很不一样, 拷贝方式的不一样, 相互影响的程度一样
浅拷贝

只拷贝引用, 拷贝和被拷贝对象, 任何一方的改变都会导致另一方的改变

let obj1 = {a:2}
let obj2 = obj1;  // 浅拷贝
深拷贝,分两种
  1. 只拷贝第一层(缺点, 对象里若有引用类型, 无法拷贝, 只能拷贝第一层)
<script>
    let obj1 = {
        name: 'zs',
        age: 100,
      	list: [1,2,4]
    } 
    // 深拷贝
    let obj2 = {};
    for( let key in obj1) { 
        obj2[key] = obj1[key];
    } 
    obj2.name = '老胡';
		obj2.list.push(555);

    console.log('obj1:',obj1);
    console.log('obj2:',obj2); 
</script>


<script>
  // 方法2
  let obj1 = {
        name: 'zs',
        age: 100,
      	list: [1,2,4]
    } 
let obj2 = {...obj1}

  
</script>
  1. 完全拷贝
<script>
    let obj1 = {
        name: 'zs',
        age: 100,
        list: [1,2,3,4,5]
    }  
    // 1.想对象变成json字符串
    let str = JSON.stringify(obj1);
    // 2.把json字符串变成对象
    let obj2 = JSON.parse(str);
    obj2.name = '老胡';
    obj2.list.push(666);

    console.log('obj1:',obj1);
    console.log('obj2:',obj2); 
</script>

(六) canvans和echarts

canvans主要用来做数据可视化

  1. 百度地图用的就是canvas
  2. 各种图标也是使用canvas进行绘制
  3. 一个基于 JavaScript 的开源可视化图表库 链接
// 使用canvas绘制一个矩形
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" /> 
  </head>
  <body> 
    <canvas id="myCanvas" width="300" height="150" style="border: 1px solid #d3d3d3" ></canvas>

    <script>
      var myCanvas = document.getElementById("myCanvas");
      var ctx = myCanvas.getContext("2d");
      ctx.fillStyle = "#FF0000";
      ctx.fillRect(20, 20, 150, 100);
    </script>
  </body>
</html>



// 使用echarts绘制图表
<template>
  <div>
    <div id="main" style="width: 300px;height: 400px;"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
export default {
  mounted() {
    this.draw();
  },
  methods: {
    draw() {
      // 获取节点
      var chartDom = document.getElementById("main");
      // 初始化echarts
      var myChart = echarts.init(chartDom);
      // 图标选项设置
      var option = {
        // 标题
        title: {
          text: "本周销量",
          x: "center",
        },
        // 横轴
        xAxis: {
          type: "category",
          // 横轴数据
          data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
        },
        // 纵轴
        yAxis: {
          type: "value",
        },
        series: [
          {
            // 纵轴数据
            data: [120, 200, 150, 80, 70, 110, 130],
            // 类型为柱状
            type: "bar",
            // 显示背景颜色
            showBackground: true,
            // 背景颜色
            backgroundStyle: {
              color: "rgba(180, 180, 180, 0.2)",
            },
          },
        ],
      };
      // 把选项放入echart对象
      myChart.setOption(option);
    },
  },
};
</script>

(七) 导出表格

  1. 安装插件 vue-json-excel
  2. 到时并使用(main.js)
import JsonExcel from 'vue-json-excel'
Vue.component('downloadExcel', JsonExcel)
  1. demo
<template>
  <div>
    <download-excel
      :data="json_data"
      :fields="json_fields"
      type="xlsx"
      worksheet="My Worksheet"
      name="我的表格.xlsx"
    >
      <el-button type="primary" size="mini">导出数据 </el-button>
    </download-excel>

    <el-table :data="json_data">
      <el-table-column label="编号" prop="id"></el-table-column>
      <el-table-column label="姓名" prop="username"></el-table-column>
      <el-table-column label="年龄" prop="age"></el-table-column>
      <el-table-column label="备注" prop="desc"></el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 表头
      json_fields: {
        编号: "id",
        姓名: "username",
        年龄: "age",
        备注: "desc",
      },
      // 表格内容
      json_data: [
        {
          id: "234",
          username: "aaa",
          age: "11",
          desc: "xxxx",
        },
        {
          id: "112",
          username: "bbb",
          age: "12",
          desc: "xxxx",
        },
      ],
    };
  },
};
</script> 

(八) 复制文本

  1. 安装插件 vue-clipboard2
  2. 导入并使用插件
// main.js
import VueClipboard from 'vue-clipboard2' 
Vue.use(VueClipboard);

  1. demo
<template>
  <div>
    <p>
      <span>{{ msg }}</span
      ><button v-clipboard:copy="msg" v-clipboard:success="onCopy">复制</button>
    </p>

    <p>
      <span>{{ msg2 }}</span
      ><button v-clipboard:copy="msg2" v-clipboard:success="onCopy">复制</button>
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: "哈哈哈哈哈哈哈哈哈哈",
      msg2: "嘿嘿嘿嘿嘿嘿",
    };
  }, 
  methods: {
    onCopy() {
      alert("复制成功");
    },
  },
};
</script>

<style>
</style>

(九) 国际化

  1. 安装插件 vue-i18n
  2. 导入和配置插件
  3. this.$i18n.locale 可以修改语言
// 配置语言包, /src/lang目录下新建en.js和zh.js
// en.js
export const lang = {
    account: 'account',
    password: 'password',
}
// zh.js
export const lang = {
    account: '账号',
    password: '密码',
}
 

// main.js
import VueI18n from "vue-i18n/dist/vue-i18n.esm.js";
Vue.use(VueI18n); // 通过插件的形式挂载
const i18n = new VueI18n({
  locale: store.state.lang, // 语言标识
  // this.$i18n.locale // 通过切换locale的值来实现语言切换
  messages: {
    "zh": require("./lang/zh"), // 中文语言包
    "en": require("./lang/en"), // 英文语言包
  },
});

// 使用
<template>
  <div>
    <p>{{ $t("lang.account") }}: zhangsan</p>
    <p>{{ $t("lang.password") }}: 123456</p>

    <button @click="handClick">切换语言</button>
  </div>
</template>

<script>
export default {
  methods: {
    handClick() {
      if (this.$i18n.locale === "en") {
        this.$i18n.locale = "zh";
      } else {
        this.$i18n.locale = "en";
      }
    },
  },
};
</script> 


(十) ElementUI库常用组件

(1) 成功或失败的消息提示

<script lang="ts" setup>
import { ElMessage } from 'element-plus'

const open1 = () => {
  ElMessage('this is a message.')
}
const open2 = () => {
  ElMessage({
    message: 'Congrats, this is a success message.',
    type: 'success',
  })
} 
const open4 = () => {
  ElMessage.error('Oops, this is a error message.')
}
</script>